/**
 * ES6 测试
 *
 * http://es6.ruanyifeng.com/#docs/let
 */
// let map = new Map();
// map.set('key1', 'value1');
// map.set('key2', 'value2');
//
// for (let [key] of map) {
//   console.log(key);
// }
//
// for (let [, value] of map) {
//   console.log(value);
// }
//
// console.log('\u{41}\u{42}\u{43}');
//
// let s = '𠮷a';
//
// for (let ch of s) {
//   console.log(ch.codePointAt(0).toString(16));
// }
//
// function is32Bit(c) {
//   return c.codePointAt(0) > 0xFFFF;
// }
//
// console.log(is32Bit('𠮷'));  // true
// console.log(is32Bit('a'));   // false
//
// console.log(String.fromCodePoint(0x20bb7));
// console.log(String.fromCodePoint(0x78, 0x1f680, 0x79, 0x1f600));
//
// let smile = '😀';
// console.log(smile.codePointAt(0).toString(16));
//
// for (let i = 1; i <= 100; i++) {
//   console.log(i.toString().padStart(3, '0'));
// }

// // 写法一
// let str = 'return ' + '`Hello ${name}!`';
// let func = new Function('name', str);

// // 写法二
// let str = '(name) => `Hello ${name}!`';
// let func = eval.call(null, str);

// console.log(func('jack'));

// let template = `
// <ul>
//   <% for(let i=0; i < data.supplies.length; i++) { %>
//     <li><%= data.supplies[i] %></li>
//     <div><%= data.supplies[i] %></div>
//   <% } %>
// </ul>
// `;
//
// function compile(template){
//   const evalExpr = /<%=(.+?)%>/g;
//   const expr = /<%([\s\S]+?)%>/g;
//
//   template = template
//     .replace(evalExpr, '`); \n  echo($1); \n  echo(`')
//     .replace(expr, '`); \n $1 \n  echo(`');
//
//   template = 'echo(`' + template + '`);';
//
//   let script =
//     `(function parse(data){
//     let output = "";
//
//     function echo(html){
//       output += html;
//     }
//
//     ${ template }
//
//     return output;
//   })`;
//
//   return script;
// }
//
// let parse = eval(compile(template));
// let aaa = parse({ supplies: [ "broom", "mop", "cleaner" ] });
//
// console.log(aaa);

// 标签模板
// let a = 5;
// let b = 10;
//
// tag`Hello ${ a + b } world ${ a * b }`;
//
// function tag(stringArr, ...values) {
//   console.log(stringArr, values);
// }

// // “标签模板”的一个重要应用，就是过滤 HTML 字符串，防止用户输入恶意内容。
// function SaferHTML(templateData) {
//   console.log(arguments);
//   let s = templateData[0];
//   for (let i = 1; i < arguments.length; i++) {
//     let arg = String(arguments[i]);
//
//     // Escape special characters in the substitution.
//     s += arg
//       .replace(/&/g, "&amp;")
//       .replace(/</g, "&lt;")
//       .replace(/>/g, "&gt;");
//
//     // Don't escape special characters in the template.
//     s += templateData[i];
//   }
//
//   return s;
// }
//
// let sender = '<script>alert("abc")</script>'; // 恶意代码
// let message = SaferHTML`<p>${sender} has sent you a message.</p>`;
// console.log(message);

// let s = '𠮷';
// console.log(/^.$/.test(s));
// console.log(/^.$/u.test(s));  // 对于码点大于0xFFFF的 Unicode 字符，点字符不能识别，必须加上u修饰符。
//
// const a = { k1: 'v1', k2: 'v2' };
// const b = {
//   k1: 'v1',
//   k2: 'v2',
// };
//
// // 立即执行函数可以写成箭头函数的形式。
// (() => {
//   console.log('123');
// })();
//
// {
//   console.log('456');
// }
//
// function concatenateAll(...args) {
//   return args.join('');
// }
//
// // console.log(concatenateAll`我是一颗小${'白菜'}${'白菜'}${'白菜'}`);
//
// function foo(x = 5, y = 6) {
//   console.log(x, y);
// }
//
// foo(undefined, 9);

// function foo() {};
// console.log(foo.name);
// console.log(foo.bind({}).name);

// let getTempItem = id => ({ id: id, name: 'Temp' });
//
// console.log(getTempItem('123'));
//
// const numbers = (...nums) => nums;
// console.log(numbers(1, 2, 3, 4, 5));
//
// const headAndTail = (head, ...tail) => [head, tail];
// console.log(headAndTail(1, 2, 3, 4, 5));
//
// function foo() {
//   setTimeout(() => {
//     console.log('id:', this.id);
//   }, 100);
// }
//
// let id = 21;
// foo.call({ id: 42 });
//
// function Timer() {
//   this.s1 = 0;
//   this.s2 = 0;
//   // 箭头函数
//   setInterval(() => {
//     this.s1++;
//     console.log(this.s1)
//   }, 1000);
//   // 普通函数
//   setInterval(function() {
//     this.s2++;
//   }, 1000);
// }

// var timer = new Timer();
// setTimeout(() => console.log('s1: ', timer.s1), 3100);
// setTimeout(() => console.log('s1: ', timer.s1), 3100);

// var handler = {
//   id: '123456',
//
//   init: function() {
//     document.addEventListener('click',
//       event => this.doSomething(event.type), false);
//   },
//
//   doSomething: function(type) {
//     console.log('Handling ' + type + ' for ' + this.id);
//   },
// };

// let a = (function() {
//   return [
//     (() => this.x).bind({ x: 'inner' })(),
//   ];
// }).call({ x: 'outer' });
//
// console.log(a);

let print = console.log.bind();

let s = Symbol();
// // 完整模式
// let obj = {
//   [s]: function(arg) {
//     print(arg);
//   },
// };
// 增强的对象写法
// let obj = {
//   [s](arg) {
//     print(arg);
//   },
// };
//
// obj[s](123);
//
// const log = {};
// log.levels = {
//   DEBUG: Symbol('debug'),
//   INFO: Symbol('info'),
//   WARN: Symbol('warn'),
// };
//
// print(log.levels.DEBUG, 'debug message');
// print(log.levels.INFO, 'info message');
//
// const COLOR_RED = Symbol();
// const COLOR_GREEN = Symbol();
//
// function getComplement(color) {
//   switch (color) {
//     case COLOR_RED:
//       return COLOR_GREEN;
//     case COLOR_GREEN:
//       return COLOR_RED;
//     default:
//       throw new Error('Undefined color');
//   }
// }

// const obj = {};
// let a = Symbol('a');
// let b = Symbol('b');
//
// obj[a] = 'Hello';
// obj[b] = 'World';
//
// const objectSymbols = Object.getOwnPropertySymbols(obj);
//
// console.log(objectSymbols); // [ Symbol(a), Symbol(b) ]

// const obj = {
//   [Symbol('my_key')]: 1,
//   enum: 2,
//   nonEnum: 3,
// };
//
// const ownKeys = Reflect.ownKeys(obj);
// console.log(ownKeys); // [ 'enum', 'nonEnum', Symbol(my_key) ]

// let size = Symbol('size');
//
// class Collection {
//   constructor() {
//     this[size] = 0;
//   }
//
//   add(item) {
//     this[this[size]] = item;
//     this[size]++;
//   }
//
//   static sizeOf(instance) {
//     const s = instance[size];
//     console.log(s);
//     return s;
//   }
// }
//
// let x = new Collection();
// Collection.sizeOf(x);
//
// x.add('foo');
// Collection.sizeOf(x);
// x.add('fee');
// Collection.sizeOf(x);
//
// console.log(Object.keys(x));
//
// console.log(x);

// function timeout(ms) {
//   return new Promise(resolve => {
//     setTimeout(resolve, ms);
//   });
// }
//
// async function asyncPrint(value, ms) {
//   console.log('开始时间：' + new Date());
//   await timeout(ms);
//   console.log('结束时间：' + new Date());
//   console.log(value);
// }
//
// asyncPrint('hello world', 3000);

// async function f() {
//   throw new Error('出错了');
// }
//
// f().then(
//   v => console.log(v),
//   e => console.log(e.message),
// );
//
// async function getTitle(url) {
//   await Promise.reject('直接滚犊子').catch(e => console.log(e));
//   let response = await fetch(url);
//   let html = await response.text();
//   return html.match(/<title>([\s\S]+)<\/title>/i)[1];
// }
//
// getTitle('https://tc39.github.io/ecma262/')
//   .then(
//     response => console.log(response.json()),
//     err => console.log(err),
//   );

// await 命令
// async function f() {
//   // 等同于
//   // return 123;
//   return await 123;
// }
//
// f().then(v => console.log(v));
//
// async function f1() {
//   try {
//     await Promise.reject(new Error('出错了'));
//   } catch (e) {
//     console.log(e.message);
//   }
//   return await Promise.resolve('hello world');
// }
//
// f1().then(v => console.log(v));

// function spawn(genF) {
//   return new Promise(function(resolve, reject) {
//     const gen = genF();
//
//     function step(nextF) {
//       let next;
//       try {
//         next = nextF();
//       } catch (e) {
//         return reject(e);
//       }
//
//       if (next.done) {
//         return resolve(next.value);
//       }
//       Promise.resolve(next.value).then(function(v) {
//         step(function() {
//           return gen.next(v);
//         })
//       }, function(e) {
//         step(function() {
//           return gen.throw(e);
//         })
//       })
//     }
//
//     step(function() {
//       return gen.next(undefined);
//     })
//   })
// }
//
// async function f() {
//   // return new Promise((resolve, reject) => {
//   //   resolve('Hello');
//   // })
//
//   return new Promise(function(resolve, reject) {
//     resolve('HHHH');
//   });
// }
//
// f().then(
//   v => console.log(v),
// );

